Fail2Ban
Fail2Ban is a log-based intrusion prevention tool that monitors service logs for suspicious activity (such as repeated authentication failures) and applies temporary bans using the host firewall. It is commonly used to reduce brute-force attempts against SSH and other internet-exposed services on Linux servers.
As brute-force attacks became routine on public servers, administrators needed a lightweight way to react automatically to repeated failures without deploying full IDS/IPS systems. Fail2Ban emerged as a pragmatic approach: watch logs for known failure patterns and apply short-lived firewall blocks to slow attackers and reduce noise.
Fail2Ban is widely deployed on VPS and cloud servers, particularly for SSH hardening and basic protection for common services. It is often paired with a baseline host firewall policy (UFW, iptables/nftables, or firewalld) and external perimeter controls (cloud security groups, reverse proxies).
Maintained by
- Maintained by the Fail2Ban community.
Best When to Use
- You need automated mitigation for brute-force attempts against SSH and other log-producing services.
- You run a small-to-medium fleet where host-local protection is acceptable.
- You already have a host firewall enabled and want dynamic temporary bans.
- You want a low-overhead complement to upstream controls (cloud security groups, CDN/WAF).
Not Suitable When
- You need deep packet inspection, protocol analysis, or payload signatures (use IDS/IPS tooling).
- You cannot rely on consistent log output (custom services without reliable logs).
- You require centralized enforcement and correlation across many hosts as the primary control (use SIEM/EDR + centralized policy).
- You expect attackers to rotate IPs rapidly and need upstream rate limiting or bot mitigation.
Compatibility Notes
-
Works best on distributions with systemd and consistent logging (journald and/or traditional log files).
-
SSH logs differ by distro and configuration:
- Debian/Ubuntu commonly use
/var/log/auth.log - RHEL/Fedora commonly use
/var/log/secure
- Debian/Ubuntu commonly use
-
Firewall backend depends on system configuration:
- UFW (Ubuntu-friendly)
- iptables/nftables (direct)
- firewalld (common on RHEL/Fedora)
-
Containers typically inherit host networking and firewalling behavior; Fail2Ban is usually configured on the host.
A misconfigured jail can ban your own IP or block SSH unexpectedly. Always confirm SSH access rules before enabling bans, keep console/serial recovery access available, and start with conservative thresholds.
Concepts and How It Works
Fail2Ban has three core building blocks:
| Component | Purpose |
|---|---|
| Filters | Regular expressions that match suspicious log entries |
| Jails | Define what to monitor and how to ban (thresholds, times, actions) |
| Actions | The ban mechanism (firewall rule insertion, notifications, etc.) |
Prerequisites
- Root or
sudoprivileges - A supported firewall backend enabled (UFW, iptables/nftables, or firewalld)
- Reliable logs for the services you want to protect (SSH, web auth, mail, etc.)
- Log rotation configured and disk space monitored
Installation
Debian/Ubuntu
sudo apt update
sudo apt install fail2ban
RHEL/CentOS Stream/Fedora
sudo dnf install fail2ban
Alpine
sudo apk add fail2ban
Safe Validation Before Changes
Start with read-only checks to confirm Fail2Ban is installed and can see logs.
Check service status
sudo systemctl status fail2ban --no-pager
Check overall Fail2Ban status
sudo fail2ban-client status
View recent Fail2Ban logs
sudo tail -n 200 /var/log/fail2ban.log 2>/dev/null || true
sudo journalctl -u fail2ban -n 200 --no-pager
Configuration Files and Layout
| File/Directory | Typical Path | Purpose |
|---|---|---|
| Main config | /etc/fail2ban/fail2ban.conf | Core daemon settings (rarely edited directly) |
| Default jails | /etc/fail2ban/jail.conf | Vendor defaults (do not edit directly) |
| Local overrides | /etc/fail2ban/jail.local or /etc/fail2ban/jail.d/*.local | Your configuration (recommended) |
| Filters | /etc/fail2ban/filter.d/ | Regex filters that detect patterns |
| Log file | /var/log/fail2ban.log | Fail2Ban activity log (if enabled) |
Avoid editing jail.conf. Use jail.local or files in jail.d/ so updates do not overwrite your settings.
Create a Baseline SSH Jail
Use a dedicated override file, which is easier to manage than a large jail.local.
Debian/Ubuntu example
Create /etc/fail2ban/jail.d/sshd.local:
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 5
findtime = 10m
bantime = 1h
backend = systemd
Apply changes:
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
RHEL/Fedora example
Create /etc/fail2ban/jail.d/sshd.local:
[sshd]
enabled = true
port = ssh
logpath = /var/log/secure
maxretry = 5
findtime = 10m
bantime = 1h
backend = systemd
Apply changes:
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
If your server is frequently accessed from variable IPs (home ISP, mobile), use a higher maxretry and shorter bantime initially to reduce accidental lockouts.
Firewall Backend Notes
Fail2Ban can apply bans using different actions depending on your firewall.
Common choices:
- UFW systems often use
banaction = ufw - iptables systems use
iptables-multiport - nftables systems use
nftables-multiport - firewalld systems use
firewallcmd-ipset
You can set the default ban action under [DEFAULT] in jail.local or a file in jail.d/.
Example snippet (UFW):
[DEFAULT]
banaction = ufw
Example snippet (nftables):
[DEFAULT]
banaction = nftables-multiport
Not all actions are packaged the same way across distributions. Confirm available actions in /etc/fail2ban/action.d/ before selecting a custom banaction.
Common Commands
Service control
sudo systemctl start fail2ban
sudo systemctl stop fail2ban
sudo systemctl restart fail2ban
sudo systemctl reload fail2ban
Status and jail inspection
sudo fail2ban-client status
sudo fail2ban-client status sshd
Manually ban and unban
sudo fail2ban-client set sshd banip 203.0.113.10
sudo fail2ban-client set sshd unbanip 203.0.113.10
Some references use fail2ban-client unban <IP>, but the reliable syntax is fail2ban-client set <jail> unbanip <IP>.
Practical Use Cases
Reduce SSH brute force noise
- Enable the
sshdjail - Ensure SSH is restricted at the firewall (allow only required sources if possible)
- Use strong authentication (keys) and disable password auth when feasible
Protect a web admin endpoint (example pattern)
For web apps that log authentication failures to a file, Fail2Ban can monitor that log with a custom filter and jail. Ensure:
- Logs are consistent and include source IPs
- The filter is tested before enabling bans
Safe workflow:
- Create filter in
/etc/fail2ban/filter.d/ - Run Fail2Ban in monitoring mode (jail enabled with higher thresholds)
- Review bans and false positives
- Tighten thresholds gradually
Troubleshooting
| Symptom | Likely Cause | Safe Checks | Fix |
|---|---|---|---|
| - | - | ||
Jail shows 0 failures despite attacks | Wrong logpath or backend | fail2ban-client status <jail>, check logs exist | Fix logpath, set backend = systemd if using journald |
| You get banned unexpectedly | Threshold too aggressive or shared IP | fail2ban-client status <jail> | Increase maxretry, reduce bantime, whitelist trusted IPs |
| Bans do not block traffic | Wrong banaction for firewall | Check /etc/fail2ban/action.d/, firewall status | Set correct banaction, restart Fail2Ban |
| High CPU / frequent restarts | Log volume too high or regex too broad | Review Fail2Ban logs | Narrow filters, reduce monitored log volume |
| SSH access lost | Your IP banned or firewall rules changed | Use console access | Unban your IP, disable jail temporarily, verify SSH allow rules |
Whitelisting Trusted IPs
Whitelisting prevents trusted sources from being banned.
Add to a local override (for example /etc/fail2ban/jail.d/local-defaults.local):
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
Apply:
sudo systemctl restart fail2ban
Whitelisting broad ranges (such as office networks or VPN subnets) reduces protection. Prefer the smallest set of trusted IPs that matches operational needs.
Security Notes
- Fail2Ban is a mitigation layer, not a primary firewall policy.
- Prefer SSH keys over passwords and disable password authentication when possible.
- Use upstream controls (cloud security groups, reverse proxies, WAF/CDN) to reduce attack surface.
- Monitor ban activity and tune thresholds based on real traffic patterns.
Emergency Recovery
If you are locked out of SSH, use out-of-band access (cloud console/serial/KVM) to recover.
Temporarily stop Fail2Ban
sudo systemctl stop fail2ban
Unban your IP (after regaining access)
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip <your-ip>
If the firewall is the cause
Verify firewall rules and restore SSH access safely before re-enabling bans. Use read-only inspection first:
sudo ufw status verbose 2>/dev/null || true
sudo iptables -S 2>/dev/null || true
sudo nft list ruleset 2>/dev/null || true
sudo firewall-cmd --state 2>/dev/null || true
Quick Reference Cheat Sheet
| Goal | Command |
|---|---|
| - | -- |
| Overall status | sudo fail2ban-client status |
| Jail status | sudo fail2ban-client status sshd |
| Restart service | sudo systemctl restart fail2ban |
| View logs (file) | sudo tail -n 200 /var/log/fail2ban.log |
| View logs (journal) | sudo journalctl -u fail2ban -n 200 --no-pager |
| Ban IP | sudo fail2ban-client set sshd banip <ip> |
| Unban IP | sudo fail2ban-client set sshd unbanip <ip> |